package me.magicall.test.db.spring;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import me.magicall.lang.reflect.proxy.ProxyUtil;
import me.magicall.lang.reflect.proxy.bean.BeanProxy;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.RowMapperResultSetExtractor;
import org.springframework.jdbc.support.JdbcUtils;

/**
 * 此类用于将数据库表的一条记录转为相应的java bean。
 * 将若干条记录解析为List，参考和使用{@link RowMapperResultSetExtractor}
 * 
 * @author MaGiCalL
 * @param <T>
 */
public class BeanProxyRowMapper<T> {

	private final Class<T> beanInterfaceClass;
	private final RowMapper rowMapper;

	public BeanProxyRowMapper(final Class<T> beanInterfaceClass) {
		if (!beanInterfaceClass.isInterface()) {
			throw new IllegalArgumentException("Class should be an interface");
		}
		this.beanInterfaceClass = beanInterfaceClass;
		rowMapper = new RowMapperImpl(beanInterfaceClass);
	}

	@SuppressWarnings("unchecked")
	public T mapRow(final ResultSet resultSet, final int rowNum) throws SQLException {
		return (T) rowMapper.mapRow(resultSet, rowNum);
	}

	RowMapper getRowMapper() {
		return rowMapper;
	}

	private static class RowMapperImpl implements RowMapper {
		private final Class<?> clazz;

		public RowMapperImpl(final Class<?> clazz) {
			super();
			this.clazz = clazz;
		}

		@Override
		public Object mapRow(final ResultSet resultSet, final int rowNum) throws SQLException {
			final BeanProxy beanProxy = new BeanProxy();
			final ResultSetMetaData rsmd = resultSet.getMetaData();
			final int columnCount = rsmd.getColumnCount();

			for (int i = 1; i <= columnCount; i++) {
				final String columnName = JdbcUtils.lookupColumnName(rsmd, i).toLowerCase();
				beanProxy.set(columnName, resultSet.getObject(i));
			}

			return ProxyUtil.newProxyInstance(beanProxy, clazz);
		}
	}

	public Class<T> getBeanInterfaceClass() {
		return beanInterfaceClass;
	}
}
